package com.xishu.client;

import com.aliyuncs.DefaultAcsClient;
import com.aliyuncs.IAcsClient;
import com.aliyuncs.dm.model.v20151123.SingleSendMailRequest;
import com.aliyuncs.dm.model.v20151123.SingleSendMailResponse;
import com.aliyuncs.profile.DefaultProfile;
import com.aliyuncs.profile.IClientProfile;
import com.xishu.config.Config;
import net.sf.json.JSONObject;
import org.apache.commons.lang.StringUtils;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import software.amazon.awssdk.core.SdkBytes;
import software.amazon.awssdk.regions.Region;
import software.amazon.awssdk.services.ses.SesClient;
import software.amazon.awssdk.services.ses.model.RawMessage;
import software.amazon.awssdk.services.ses.model.SendRawEmailRequest;
import software.amazon.awssdk.services.ses.model.SesException;

import javax.activation.DataHandler;
import javax.activation.DataSource;
import javax.activation.FileDataSource;
import javax.mail.BodyPart;
import javax.mail.Message;
import javax.mail.Session;
import javax.mail.internet.InternetAddress;
import javax.mail.internet.MimeBodyPart;
import javax.mail.internet.MimeMessage;
import javax.mail.internet.MimeMultipart;
import java.io.ByteArrayOutputStream;
import java.io.File;
import java.nio.ByteBuffer;
import java.util.Properties;

public class EmailClient {
    private static Logger logger = LoggerFactory.getLogger(EmailClient.class);
    public static final String DOLA_SENDER_NAME = "DoLA Technology <donotreply@dolatechnology.com>";

    private static EmailClient instance = new EmailClient();

    public EmailClient() {
    }

    public static EmailClient getInstance() {
        return instance;
    }

    public void sendEmail(String emailAddress, String title, String content) throws Exception {
        Config config = Config.getInstance();

        if (config.performanceTest()) {
            logger.info("performance test");
            return;
        }

        if (config.isAliyun()) {
            aliyunSendEmail(emailAddress, title, content);
        } else {
            awsSendEmail(DOLA_SENDER_NAME, emailAddress, title, content, null);
        }
    }

    public void sendEmail(String emailAddress, String title, String content, File attachFile) throws Exception {
        Config config = Config.getInstance();

        if (config.performanceTest()) {
            logger.info("performance test");
            return;
        }

        if (config.isAliyun()) {
            aliyunSendEmail(emailAddress, title, content);
        } else {
            awsSendEmail(DOLA_SENDER_NAME, emailAddress, title, content, attachFile);
        }
    }


    /**
     * 发送邮件
     *
     * @param senderName
     * @param emailAddress
     * @param title
     * @param content
     */
    public void sendEmail(String senderName, String emailAddress, String title, String content, File attachFile) throws Exception {
        Config config = Config.getInstance();

        if (config.performanceTest()) {
            logger.info("performance test");
            return;
        }

        if (config.isAliyun()) {
            aliyunSendEmail(emailAddress, title, content);
        } else {

            if (StringUtils.isEmpty(emailAddress)) {
                senderName = DOLA_SENDER_NAME;
            }

            awsSendEmail(senderName, emailAddress, title, content, attachFile);
        }
    }

    /**
     * 亚马逊发送邮件
     * <p>
     * US East (Ohio)	us-east-2
     * email.us-east-2.amazonaws.com
     * <p>
     * HTTPS
     * US East (N. Virginia)	us-east-1
     * email.us-east-1.amazonaws.com
     * <p>
     * email-fips.us-east-1.amazonaws.com
     * <p>
     * HTTPS
     * US West (N. California)	us-west-1
     * email.us-west-1.amazonaws.com
     * <p>
     * HTTPS
     * US West (Oregon)	us-west-2
     * email.us-west-2.amazonaws.com
     * <p>
     * email-fips.us-west-2.amazonaws.com
     * <p>
     * HTTPS
     * Africa (Cape Town)	af-south-1
     * email.af-south-1.amazonaws.com
     * <p>
     * HTTPS
     * Asia Pacific (Mumbai)	ap-south-1
     * email.ap-south-1.amazonaws.com
     * <p>
     * HTTPS
     * Asia Pacific (Seoul)	ap-northeast-2
     * email.ap-northeast-2.amazonaws.com
     * <p>
     * HTTPS
     * Asia Pacific (Singapore)	ap-southeast-1
     * email.ap-southeast-1.amazonaws.com
     * <p>
     * HTTPS
     * Asia Pacific (Sydney)	ap-southeast-2
     * email.ap-southeast-2.amazonaws.com
     * <p>
     * HTTPS
     * Asia Pacific (Tokyo)	ap-northeast-1
     * email.ap-northeast-1.amazonaws.com
     * <p>
     * HTTPS
     * Canada (Central)	ca-central-1
     * email.ca-central-1.amazonaws.com
     * <p>
     * HTTPS
     * Europe (Frankfurt)	eu-central-1
     * email.eu-central-1.amazonaws.com
     * <p>
     * HTTPS
     * Europe (Ireland)	eu-west-1
     * email.eu-west-1.amazonaws.com
     * <p>
     * HTTPS
     * Europe (London)	eu-west-2
     * email.eu-west-2.amazonaws.com
     * <p>
     * HTTPS
     * Europe (Milan)	eu-south-1
     * email.eu-south-1.amazonaws.com
     * <p>
     * HTTPS
     * Europe (Paris)	eu-west-3
     * email.eu-west-3.amazonaws.com
     * <p>
     * HTTPS
     * Europe (Stockholm)	eu-north-1
     * email.eu-north-1.amazonaws.com
     * <p>
     * HTTPS
     * Middle East (Bahrain)	me-south-1
     * email.me-south-1.amazonaws.com
     * <p>
     * HTTPS
     * South America (São Paulo)	sa-east-1
     * email.sa-east-1.amazonaws.com
     * <p>
     * HTTPS
     * AWS GovCloud (US)	us-gov-west-1
     * email.us-gov-west-1.amazonaws.com
     * <p>
     * email-fips.us-gov-west-1.amazonaws.com
     * <p>
     * HTTPS
     *
     * @param emailAddress
     * @param title
     * @param content
     */
    public void awsSendEmail(String senderName, String emailAddress, String title, String content, File attachFile) throws Exception {

        SesClient client = SesClient.builder()
                .region(Region.US_EAST_1)
                .build();

        try {
            send(client, senderName, emailAddress, title, content, attachFile);
        } finally {
            client.close();
        }

    }

    // snippet-start:[ses.java2.sendmessage.main]
    public static void send(SesClient client,
                            String sender,
                            String recipient,
                            String subject,
                            String bodyHTML,
                            File attachFile
    ) throws Exception {
        logger.info("{} to {}, subject {}", sender, recipient, subject);

        Session session = Session.getDefaultInstance(new Properties());
        MimeMessage message = new MimeMessage(session);

        // Add subject, from and to lines
        message.setSubject(subject, "UTF-8");
        message.setFrom(new InternetAddress(sender));
        message.setRecipients(Message.RecipientType.TO, InternetAddress.parse(recipient));

        // Create a multipart/alternative child container
        MimeMultipart msgBody = new MimeMultipart("alternative");

        // Create a wrapper for the HTML and text parts
        MimeBodyPart wrap = new MimeBodyPart();

        // Define the HTML part
        MimeBodyPart htmlPart = new MimeBodyPart();
        htmlPart.setContent(bodyHTML, "text/html; charset=UTF-8");

//        if (attachFile != null) {
//            MimeBodyPart mimeBodyPart = new MimeBodyPart();
//            mimeBodyPart.attachFile(attachFile);
//            msgBody.addBodyPart(mimeBodyPart);
//        }


        // Add the text and HTML parts to the child container
        msgBody.addBodyPart(htmlPart);

        // Add the child container to the wrapper object
        wrap.setContent(msgBody);

        // Create a multipart/mixed parent container
        MimeMultipart msg = new MimeMultipart("mixed");
        if (attachFile != null) {
            MimeBodyPart att = new MimeBodyPart();
            DataSource fds = new FileDataSource(attachFile);
            att.setDataHandler(new DataHandler(fds));
            att.setFileName(fds.getName());
            msg.addBodyPart(att);
        }

        // Add the parent container to the message
        message.setContent(msg);

        // Add the multipart/alternative part to the message
        msg.addBodyPart(wrap);

        try {
            logger.info("Attempting to send an email through Amazon SES " + "using the AWS SDK for Java...");

            ByteArrayOutputStream outputStream = new ByteArrayOutputStream();
            message.writeTo(outputStream);
            ByteBuffer buf = ByteBuffer.wrap(outputStream.toByteArray());

            byte[] arr = new byte[buf.remaining()];
            buf.get(arr);

            SdkBytes data = SdkBytes.fromByteArray(arr);
            RawMessage rawMessage = RawMessage.builder()
                    .data(data)
                    .build();

            SendRawEmailRequest rawEmailRequest = SendRawEmailRequest.builder()
                    .rawMessage(rawMessage)
                    .build();

            client.sendRawEmail(rawEmailRequest);
            logger.info("send email end");
        } catch (SesException e) {
            System.err.println(e.awsErrorDetails().errorMessage());
            logger.error("e", e);
        }
    }


    /**
     * 阿里云发送邮件
     *
     * @param emailAddress
     * @param title
     * @param content
     * @throws com.aliyuncs.exceptions.ClientException
     */
    public void aliyunSendEmail(String emailAddress, String title, String content) throws com.aliyuncs.exceptions.ClientException {
        Config config = Config.getInstance();
        IClientProfile profile = DefaultProfile.getProfile("cn-hangzhou", config.getEmailAk(), config.getEmailSk());
        IAcsClient client = new DefaultAcsClient(profile);
        SingleSendMailRequest request = new SingleSendMailRequest();
        request.setAccountName("cd-xishu@email.cd-xishu.com");
        request.setFromAlias("Dola");
        request.setAddressType(1);
        request.setReplyToAddress(true);
        request.setToAddress(emailAddress);
        //可以给多个收件人发送邮件，收件人之间用逗号分开，批量发信建议使用BatchSendMailRequest方式
        //request.setToAddress("邮箱1,邮箱2");
        request.setSubject(title);
        request.setHtmlBody(content);
        SingleSendMailResponse httpResponse = client.getAcsResponse(request);
        logger.info("httpResponse is {}", JSONObject.fromObject(httpResponse));
    }


}
